---
title: 'Decorators'
description: 'Use decorators to track activities in your agent system'
---
## Available Decorators

AgentOps provides the following decorators:

| Decorator | Purpose | Creates |
|-----------|---------|---------|
| `@session` | Track an entire user interaction | SESSION span |
| `@agent` | Track agent classes and their lifecycle | AGENT span |
| `@operation` | Track discrete operations performed by agents | OPERATION span |
| `@workflow` | Track a sequence of operations | WORKFLOW span |
| `@task` | Track smaller units of work (similar to operations) | TASK span |
| `@tool` | Track tool usage and cost in agent operations | TOOL span |
| `@guardrail` | Track guardrail input and output | GUARDRAIL span |

## Decorator Hierarchy

The decorators create spans that form a hierarchy:

```
SESSION
  ├── AGENT
  │     ├── OPERATION or TASK
  │     │     ├── LLM
  │     │     └── TOOL
  │     └── WORKFLOW
  │           └── OPERATION or TASK
  └── AGENT
        └── OPERATION or TASK
```

## Using Decorators

### @session

The `@session` decorator tracks an entire user interaction from start to finish:

```python
from agentops.sdk.decorators import session
import agentops

# Initialize AgentOps
agentops.init(api_key="YOUR_API_KEY")

@session
def answer_question(question):
    # Create and use agents
    weather_agent = WeatherAgent()
    result = weather_agent.get_forecast(question)
    
    # Return the final result
    return result
```

Each `@session` function call creates a new session span that contains all the agents, operations, and workflows used during that interaction.

### @agent

The `@agent` decorator instruments a class to track its lifecycle and operations:

```python
from agentops.sdk.decorators import agent, operation
import agentops

# Initialize AgentOps
agentops.init(api_key="YOUR_API_KEY")

@agent
class WeatherAgent:
    def __init__(self):
        self.api_key = "weather_api_key"
        
    @operation
    def get_forecast(self, location):
        # Get weather data
        return f"The weather in {location} is sunny."

def check_weather(city):
    weather_agent = WeatherAgent()
    forecast = weather_agent.get_forecast(city)
    return forecast

weather_info = check_weather("San Francisco")
```

When an agent-decorated class is instantiated within a session, an AGENT span is created automatically.

### @operation

The `@operation` decorator tracks discrete functions performed by an agent:

```python
from agentops.sdk.decorators import agent, operation
import agentops

# Initialize AgentOps
agentops.init(api_key="YOUR_API_KEY")

@agent
class MathAgent:
    @operation
    def add(self, a, b):
        return a + b
        
    @operation
    def multiply(self, a, b):
        return a * b

def calculate(x, y):
    math_agent = MathAgent()
    sum_result = math_agent.add(x, y)
    product_result = math_agent.multiply(x, y)
    return {"sum": sum_result, "product": product_result}

results = calculate(5, 3)
```

Operations represent the smallest meaningful units of work in your agent system. Each operation creates an OPERATION span with:
- Inputs (function arguments)
- Output (return value)
- Duration
- Success/failure status

### @workflow

The `@workflow` decorator tracks a sequence of operations that work together:

```python
from agentops.sdk.decorators import agent, operation, workflow
import agentops

# Initialize AgentOps
agentops.init(api_key="YOUR_API_KEY")

@agent
class TravelAgent:
    def __init__(self):
        self.flight_api = FlightAPI()
        self.hotel_api = HotelAPI()
    
    @workflow
    def plan_trip(self, destination, dates):
        # This workflow contains multiple operations
        flights = self.find_flights(destination, dates)
        hotels = self.find_hotels(destination, dates)
        
        return {
            "flights": flights,
            "hotels": hotels
        }
        
    @operation
    def find_flights(self, destination, dates):
        return self.flight_api.search(destination, dates)
        
    @operation
    def find_hotels(self, destination, dates):
        return self.hotel_api.search(destination, dates)
```

Workflows help you organize related operations and see their collective performance.

### @task

The `@task` decorator is similar to `@operation` but can be used for smaller units of work:

```python
from agentops.sdk.decorators import agent, task
import agentops

# Initialize AgentOps
agentops.init(api_key="YOUR_API_KEY")

@agent
class DataProcessor:
    @task
    def normalize_data(self, data):
        # Normalize the data
        return [x / sum(data) for x in data]
    
    @task
    def filter_outliers(self, data, threshold=3):
        # Filter outliers
        mean = sum(data) / len(data)
        std_dev = (sum((x - mean) ** 2 for x in data) / len(data)) ** 0.5
        
        return [x for x in data if abs(x - mean) <= threshold * std_dev]
```

The `@task` and `@operation` decorators function identically (they are aliases in the codebase), and you can choose the one that best fits your semantic needs.

### @tool

The `@tool` decorator tracks tool usage within agent operations and supports cost tracking. It works with all function types: synchronous, asynchronous, generator, and async generator.

```python
from agentops.sdk.decorators import agent, tool
import asyncio

@agent
class ProcessingAgent:
    def __init__(self):
        pass

    @tool(cost=0.01)
    def sync_tool(self, item):
        """Synchronous tool with cost tracking."""
        return f"Processed {item}"

    @tool(cost=0.02)
    async def async_tool(self, item):
        """Asynchronous tool with cost tracking."""
        await asyncio.sleep(0.1)
        return f"Async processed {item}"

    @tool(cost=0.03)
    def generator_tool(self, items):
        """Generator tool with cost tracking."""
        for item in items:
            yield self.sync_tool(item)

    @tool(cost=0.04)
    async def async_generator_tool(self, items):
        """Async generator tool with cost tracking."""
        for item in items:
            await asyncio.sleep(0.1)
            yield await self.async_tool(item)
```

The tool decorator provides:
- Cost tracking for each tool call
- Proper span creation and nesting
- Support for all function types (sync, async, generator, async generator)
- Cost accumulation in generator and async generator operations

### @guardrail

The `@guardrail` decorator tracks guardrail input and output. You can specify the guardrail type (`"input"` or `"output"`) with the `spec` parameter.

```python
from agentops.sdk.decorators import guardrail
import agentops
import re

# Initialize AgentOps
agentops.init(api_key="YOUR_API_KEY")

@guardrail(spec="input")
def secret_key_guardrail(input):
    pattern = r'\bsk-[a-zA-Z0-9]{10,}\b'
    result = True if re.search(pattern, input) else False
    return {
        "tripwire_triggered" : result
    }
```

## Decorator Attributes

You can pass additional attributes to decorators:

```python
from agentops.sdk.decorators import agent, operation
import agentops

# Initialize AgentOps
agentops.init(api_key="YOUR_API_KEY")

@agent(name="custom_agent_name", attributes={"version": "1.0"})
class CustomAgent:
    @operation(name="custom_operation", attributes={"importance": "high"})
    def process(self, data):
        return data
```

Common attributes include:

| Attribute | Description | Example |
|-----------|-------------|---------|
| `name` | Custom name for the span | `name="weather_forecast"` |
| `attributes` | Dictionary of custom attributes | `attributes={"model": "gpt-4"}` |

## Complete Example

Here's a complete example using all the decorators together:

```python
from agentops.sdk.decorators import session, agent, operation, workflow, task
import agentops

# Initialize AgentOps
agentops.init(api_key="YOUR_API_KEY")

@session
def assist_user(query):
    # Create the main assistant
    assistant = Assistant()
    
    # Process the query
    return assistant.process_query(query)

@agent
class Assistant:
    def __init__(self):
        pass
    
    @workflow
    def process_query(self, query):
        research_agent = ResearchAgent()
        writing_agent = WritingAgent()
        
        # Research phase
        research = research_agent.gather_information(query)
        
        # Writing phase
        response = writing_agent.generate_response(query, research)
        
        return response

@agent
class ResearchAgent:
    @operation
    def gather_information(self, query):
        # Perform web search
        search_results = self.search(query)
        
        # Analyze results
        return self.analyze_results(search_results)
    
    @task
    def search(self, query):
        # Simulate web search
        return [f"Result for {query}", f"Another result for {query}"]
    
    @task
    def analyze_results(self, results):
        # Analyze search results
        return {"summary": "Analysis of " + ", ".join(results)}

@agent
class WritingAgent:
    @operation
    def generate_response(self, query, research):
        # Generate a response based on the research
        return f"Answer to '{query}' based on: {research['summary']}"

assist_user("What is the capital of France?")
```

In this example:
1. The `@session` decorator wraps the entire interaction
2. The `@agent` decorator defines multiple agent classes
3. The `@workflow` decorator creates a workflow that coordinates agents
4. The `@operation` and `@task` decorators track individual operations
5. All spans are properly nested in the hierarchy

Note that LLM and TOOL spans are automatically created when you use compatible LLM libraries or tool integrations.

## Best Practices

- **Use @session for top-level functions** that represent complete user interactions
- **Apply @agent to classes** that represent distinct components of your system
- **Use @operation for significant functions** that represent complete units of work
- **Use @task for smaller functions** that are part of larger operations
- **Apply @workflow to methods** that coordinate multiple operations
- **Keep decorator nesting consistent** with the logical hierarchy of your code
- **Add custom attributes** to provide additional context for analysis
- **Use meaningful names** for all decorated components

## Dashboard Visualization

In the AgentOps dashboard, decorators create spans that appear in:

1. **Timeline View**: Shows the execution sequence and duration
2. **Hierarchy View**: Displays the parent-child relationships
3. **Detail Panels**: Shows inputs, outputs, and attributes
4. **Performance Metrics**: Tracks execution times and success rates

This visualization helps you understand the flow and performance of your agent system.

<script type="module" src="/scripts/github_stars.js"></script>
<script type="module" src="/scripts/scroll-img-fadein-animation.js"></script>
<script type="module" src="/scripts/button_heartbeat_animation.js"></script>